/*
 * array.c
 *
 *  Created on: Apr 21, 2011
 *      Author: mariano
 */

#include "../include/array.h"
#include <stdlib.h>

Array * copyArray(Array * other) {
	if (other == NULL || other->array == NULL)
		return NULL;

	Array * out = malloc(sizeof(Array));
	out->count = other->count;
	out->size = other->size;

	// Initializing with zeroes (NULL)
	out->array = calloc(out->size, sizeof(void *));

	int i;
	for (i = 0; i < out->count; i++)
		out->array[i] = other->array[i];

	return out;

}

Array * newArray() {
	Array * out = malloc(sizeof(Array));
	out->count = 0;
	out->size = 10;

	// Initializing with zeroes (NULL)
	out->array = calloc(out->size, sizeof(void *));

	return out;
}

void deleteArray(Array * array) {
	free(array->array);
	free(array);
}

void * getElementByIndex(Array * array, int index) {
	return index >= 0 ? array->array[index] : NULL;
}

void deleteElementFromArray(Array * array, void * element, int(*cmp)(void * e1,
		void * e2)) {
	int i, j;
	for (i = 0; i < array->count; i++) {
		if (cmp(array->array[i], element)) {
			array->count--;
			for (j = i; j < array->count; j++) {
				array->array[j] = array->array[j + 1];
			}
		}
	}
}

void deleteRepetedElementsFormArray(Array * array, int(*cmp)(void * e1,
		void * e2)) {
	int i, j, k;
	for (k = 0; k < array->count; k++) {
		for (i = 0; i < array->count; i++) {
			if (i != k && cmp(array->array[i], array->array[k])) {
				array->count--;
				for (j = array->count - 1; j >= i; j--) {
					array->array[j] = array->array[j + 1];
				}
			}
		}
	}
}

void add(Array * array, void * element) {
	if (array->count + 1 < array->size) {
		array->array[array->count] = element;
	} else {
		array->size += 10;
		array->array = realloc(array->array, array->size*sizeof(void *));
		array->array[array->count] = element;
	}
	array->count++;
}

void forEach(Array * array, void(*function)(void *)) {
	if (function == NULL || array == NULL)
		return;
	int i;
	for (i = 0; i < array->count; i++)
		function(array->array[i]);
}

Array * transformArray(Array * array, void *(*function)(void *)) {
	Array * out = newArray();
	int i;
	for (i = 0; i < array->count; i++)
		add(out, function(array->array[i]));
	return out;
}

void swap(Array * array, int i, int j) {
	void * temp = array->array[i];
	array->array[i] = array->array[j];
	array->array[j] = temp;
}

void bubleSort(Array * array, int(*cmp)(void * e1, void * e2)) {
	int i, j;
	for (i = 1; i <= array->count; i++)
		for (j = 0; j < array->count - i; j++)
			if (cmp(array->array[j], array->array[j + 1]) < 0)
				swap(array, j, j + 1);
}

int contains(Array * array, void * element, int(*cmp)(void * e1, void * e2)) {
	int i;
	for (i = 0; i < array->count; i++) {
		if (cmp(array->array[i], element)) {
			return 1;
		}
	}
	return 0;
}

Array * getElementsByFunction(Array * array, int(*func)(void * e, void * arg),
		void * arg) {
	Array * out = newArray();
	int i;
	for (i = 0; i < array->count; i++)
		if (func(array->array[i], arg) == 1)
			add(out, array->array[i]);
	return out;
}
